/**
 * AverageImageScale.java 
 * Copyright © 2015-3015, 杭州泊享网络科技有限公司
 * 
 * @author Liu Tao
 * @create 2015年1月26日
 */
package com.pshare.util.img;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import com.pshare.util.StringUtils;

/**
 * 图片裁剪缩小工具类
 * 使用方型区域颜色平均算法
 */
public class AverageImageScale {
	
	/**
	 * 缩小图片
	 * 
	 * @param input 输入流文件
	 * @param destFile 目标图片
	 * @param boxWidth 缩略图最大宽度
	 * @param boxHeight 缩略图最大高度
	 * @throws IOException
	 */
	public static void resizeFix(InputStream input, File destFile, int boxWidth, int boxHeight) throws IOException {
		BufferedImage srcImgBuff = ImageIO.read(input);
		int width = srcImgBuff.getWidth();
		int height = srcImgBuff.getHeight();
		if (width <= boxWidth && height <= boxHeight) {
			writeFile(srcImgBuff, destFile);
			return;
		}
		int zoomWidth;
		int zoomHeight;
		if ((float) width / height > (float) boxWidth / boxHeight) {
			zoomWidth = boxWidth;
			zoomHeight = Math.round((float) boxWidth * height / width);
		} else {
			zoomWidth = Math.round((float) boxHeight * width / height);
			zoomHeight = boxHeight;
		}
		BufferedImage imgBuff = scaleImage(srcImgBuff, width, height, zoomWidth, zoomHeight);
		writeFile(imgBuff, destFile);
	}

	/**
	 * 裁剪并压缩
	 * 
	 * @param srcFile 原文件
	 * @param destFile 目标文件
	 * @param boxWidth 缩略图最大宽度
	 * @param boxHeight 缩略图最大高度
	 * @param cutTop 裁剪TOP
	 * @param cutLeft 裁剪LEFT
	 * @param cutWidth 裁剪宽度
	 * @param catHeight 裁剪高度
	 * @throws IOException
	 */
	public static void resizeFix(InputStream input, File destFile, int cutTop, int cutLeft, int cutWidth, int catHeight)
			throws IOException {
		BufferedImage srcImgBuff = ImageIO.read(input);
		int boxWidth = srcImgBuff.getWidth();
		int boxHeight = srcImgBuff.getHeight();

		srcImgBuff = srcImgBuff.getSubimage(cutTop, cutLeft, cutWidth, catHeight);
		int width = srcImgBuff.getWidth();
		int height = srcImgBuff.getHeight();
		if (width <= boxWidth && height <= boxHeight) {
			writeFile(srcImgBuff, destFile);
			return;
		}
		int zoomWidth;
		int zoomHeight;
		if ((float) width / height > (float) boxWidth / boxHeight) {
			zoomWidth = boxWidth;
			zoomHeight = Math.round((float) boxWidth * height / width);
		} else {
			zoomWidth = Math.round((float) boxHeight * width / height);
			zoomHeight = boxHeight;
		}
		BufferedImage imgBuff = scaleImage(srcImgBuff, width, height, zoomWidth, zoomHeight);
		writeFile(imgBuff, destFile);
	}

	public static void writeFile(BufferedImage imgBuf, File destFile) throws IOException {
		File parent = destFile.getParentFile();
		if (!parent.exists()) {
			parent.mkdirs();
		}
		ImageIO.write(imgBuf, getExtName(destFile.getAbsolutePath()), destFile);
	}

	private static String getExtName(String fileName) {
		if (StringUtils.isBlank(fileName)) {
			return null;
		}

		fileName = StringUtils.trim(fileName);
		int pos = fileName.lastIndexOf(".");
		if (pos <= 0) {
			return null;
		}

		String extName = fileName.substring(pos + 1);
		return extName;
	}

	private static BufferedImage scaleImage(BufferedImage srcImgBuff, int width, int height, int zoomWidth,
			int zoomHeight) {
		int[] colorArray = srcImgBuff.getRGB(0, 0, width, height, null, 0, width);
		BufferedImage outBuff = new BufferedImage(zoomWidth, zoomHeight, BufferedImage.TYPE_INT_RGB);
		// 宽缩小的倍数
		float wScale = (float) width / zoomWidth;
		int wScaleInt = (int) (wScale + 0.5);
		// 高缩小的倍数
		float hScale = (float) height / zoomHeight;
		int hScaleInt = (int) (hScale + 0.5);
		int area = wScaleInt * hScaleInt;
		int x0, x1, y0, y1;
		int color;
		long red, green, blue;
		int x, y, i, j;
		for (y = 0; y < zoomHeight; y++) {
			// 得到原图高的Y坐标
			y0 = (int) (y * hScale);
			y1 = y0 + hScaleInt;
			for (x = 0; x < zoomWidth; x++) {
				x0 = (int) (x * wScale);
				x1 = x0 + wScaleInt;
				red = green = blue = 0;
				for (i = x0; i < x1; i++) {
					for (j = y0; j < y1; j++) {
						color = colorArray[width * j + i];
						red += getRedValue(color);
						green += getGreenValue(color);
						blue += getBlueValue(color);
					}
				}
				outBuff.setRGB(x, y, comRGB((int) (red / area), (int) (green / area), (int) (blue / area)));
			}
		}
		return outBuff;
	}

	/**
	 * 图片剪裁
	 * 
	 * @param is
	 * @param x
	 * @param y
	 * @param w
	 * @param h
	 * @return
	 * @throws IOException 
	 * @throws Exception
	 */
	public static InputStream cutImg(InputStream is, Integer x, Integer y, Integer w, Integer h) throws IOException {
		BufferedImage bi;
		ByteArrayOutputStream os = null;
		bi = ImageIO.read(is);
		// 创建要裁剪出来的图片
		CropImageFilter cropFilter = new CropImageFilter(x, y, w, h);
		Image tagImg = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(bi.getSource(), cropFilter));

		BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
		Graphics graphics = image.createGraphics();
		graphics.drawImage(tagImg, 0, 0, w, h, null);
		graphics.dispose();

		os = new ByteArrayOutputStream();
		ImageIO.write(image, "jpg", os);

		return new ByteArrayInputStream(os.toByteArray());
	}

	private static int getRedValue(int rgbValue) {
		return (rgbValue & 0x00ff0000) >> 16;
	}

	private static int getGreenValue(int rgbValue) {
		return (rgbValue & 0x0000ff00) >> 8;
	}

	private static int getBlueValue(int rgbValue) {
		return rgbValue & 0x000000ff;
	}

	private static int comRGB(int redValue, int greenValue, int blueValue) {
		return (redValue << 16) + (greenValue << 8) + blueValue;
	}

}
